/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * 从头到尾合并两个列表，非常慢，超过 5%
 */

/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function(lists) {
  if (lists.length === 0) return null;
  if (lists.length === 1) return lists[0];

  let r = lists[0];
  for (let i = 1; i < lists.length; i++) {
    const curr = lists[i];
    if (curr == null) continue;

    r = merge2List(r, curr);
  }
  return r;
};

function merge2List(list1, list2) {
  let r = null;
  let c = null;
  const gen = findMin(list1, list2);
  while (true) {
    const min = gen.next();
    if (min.done) break;

    if (r === null) {
      r = new ListNode(min.value);
      c = r;
    } else {
      c.next = new ListNode(min.value);
      c = c.next;
    }
  }
  return r;
}

function* findMin(list1, list2) {
  while (true) {
    if (list1 != null) {
      if (list2 != null) {
        if (list1.val < list2.val) {
          yield list1.val;
          list1 = list1.next;
        } else {
          yield list2.val;
          list2 = list2.next;
        }
      } else {
        yield list1.val;
        list1 = list1.next;
      }
    } else {
      if (list2 != null) {
        yield list2.val;
        list2 = list2.next;
      } else {
        break;
      }
    }
  }
}

// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------

function ListNode(val, next = null) {
  this.val = val;
  this.next = next;
  this.toString = () => {
    const current = '' + this.val + ', ';
    const nextStr = this.next === null ? '' : this.next.toString();
    return current + nextStr;
  };
}

const kl = [
  new ListNode(1, new ListNode(4, new ListNode(5))),
  new ListNode(1, new ListNode(3, new ListNode(4))),
  new ListNode(2, new ListNode(6))
];

console.log(mergeKLists(kl).toString());
